﻿using Autofac;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using MG.Repository;
using MG.SmartHMI.Common;
using MG.SmartHMI.Domain;
using MG.SmartHMI.Entity.DAO;
using MG.SmartHMI.Model;
using MG.SmartHMI.Model.Common;
using MG.Util.Data;
using MG.Util.Log;
using SqlSugar;

namespace MG.SmartHMI.ViewModel
{
    public partial class SlnViewModel : ObservableRecipient
    {
        #region Parm

        [ObservableProperty]
        private List<ButtonViewModel> listButton = new();

        [ObservableProperty]
        private List<CheckBoxViewModel> listCheckBox = new();

        [ObservableProperty]
        private List<SwitchViewModel> listSwitch = new();

        [ObservableProperty]
        private List<InputSignalViewModel> listInputSignal = new();

        [ObservableProperty]
        private List<InputBoxViewModel> listInputBox = new();

        [ObservableProperty]
        private List<DispBoxViewModel> listDispBox = new();

        [ObservableProperty]
        private List<AxisBoxViewModel> listAxis = new();

        [ObservableProperty]
        private bool visiblityButton;

        [ObservableProperty]
        private bool visiblityCheckBox;

        [ObservableProperty]
        private bool visiblitySwitch;

        [ObservableProperty]
        private bool visiblityInputSignal;

        [ObservableProperty]
        private bool visiblityDispBox;

        [ObservableProperty]
        private bool visiblityinputBox;

        [ObservableProperty]
        private bool visiblityAxis;

        [ObservableProperty]
        private string selectedSlnName;

        [ObservableProperty]
        private List<string> listSlnResource = new();

        private int CurrSlnId;

        partial void OnSelectedSlnNameChanged(string value)
        {
            var list = RepositoryService<SlnConfig>.Instance.Query(t => t.Name.Equals(value) && !t.IsDelete).ToList();

            if (list == null || list.Count() < 1) return;

            CurrSlnId = list.First().Id;
            Update2UI();
        }

        #endregion Parm

        #region Structure

        public SlnViewModel()
        {
            Register();
            InitUI();
        }

        #endregion Structure

        #region Command

        [RelayCommand]
        private void AddSln(string newslnname)
        {
            Task.Run(() =>
            {
                RepositoryService<SlnConfig>.Instance.Add(new SlnConfig() { Name = newslnname });
                ListSlnResource = RepositoryService<SlnConfig>.Instance.Query(t => !t.IsDelete).Select(t => t.Name).ToList();
                SelectedSlnName = RepositoryService<SlnConfig>.Instance.Query(t => t.Name.Equals(newslnname) && !t.IsDelete).FirstOrDefault()?.Name;
                EventBus.Default.PopUpSuccess("创建成功");
                EventBus.Default.Log(new LogInfo($"创建配方 [{newslnname}]"));
            });
        }

        [RelayCommand]
        private void SaveSln()
        {
            Task.Run(() =>
            {
                #region 数据保存到配方

                foreach (var item in ListCheckBox)
                {
                    RepositoryService<SlnParmConfig>.Instance.AddOrUpdate(new SlnParmConfig()
                    {
                        Id = item.SlnParmId,
                        SlnId = CurrSlnId,
                        RegisterId = item.RegisterData.Id,
                        Value = item.IsChecked.ToString(),
                        IsDelete = false
                    }, q => new { q.SlnId, q.RegisterId });
                }

                foreach (var item in ListSwitch)
                {
                    RepositoryService<SlnParmConfig>.Instance.AddOrUpdate(new SlnParmConfig()
                    {
                        Id = item.SlnParmId,
                        SlnId = CurrSlnId,
                        RegisterId = item.RegisterData.Id,
                        Value = item.IsSwitchOn.ToString(),
                        IsDelete = false
                    }, q => new { q.SlnId, q.RegisterId, q.IsDelete });
                }

                foreach (var item in ListInputBox)
                {
                    RepositoryService<SlnParmConfig>.Instance.AddOrUpdate(new SlnParmConfig()
                    {
                        Id = item.SlnParmId,
                        SlnId = CurrSlnId,
                        RegisterId = item.RegisterData.Id,
                        Value = item.InputValue,
                        IsDelete = false
                    }, q => new { q.SlnId, q.RegisterId, q.IsDelete });
                }

                #endregion 数据保存到配方

                EventBus.Default.PopUpSuccess("配置保存成功");
                EventBus.Default.Log(new LogInfo($"配置保存成功  {ListCheckBox.ToJson().FormatJson()}\r\n{ListSwitch.ToJson().FormatJson()}\r\n{ListInputBox.ToJson().FormatJson()}"));
            });
        }

        [RelayCommand]
        private void DeleteSln()
        {
            Task.Run(async () =>
            {
                RepositoryService<SlnConfig>.Instance.UpdateFiled(t => new SlnConfig() { IsDelete = true }, q => q.Id.Equals(CurrSlnId));
                RepositoryService<SlnParmConfig>.Instance.UpdateFiled(t => new SlnParmConfig() { IsDelete = true }, q => q.SlnId.Equals(CurrSlnId));
                EventBus.Default.PopUpSuccess("删除成功");
                EventBus.Default.Log(new LogInfo($"删除配方 [{SelectedSlnName}] "));

                ListSlnResource = RepositoryService<SlnConfig>.Instance.Query(t => !t.IsDelete).Select(t => t.Name).ToList();
                await Task.Delay(50);//等待数据库执行结束
                SelectedSlnName = RepositoryService<SlnConfig>.Instance.Query(t => !t.IsDelete).FirstOrDefault()?.Name;
            });
        }

        [RelayCommand]
        private void SlnRead()
        {
            Task.Run(() =>
            {
                ListCheckBox.ForEach(t => t.UpdateRead());
                ListSwitch.ForEach(t => t.UpdateRead());
                ListInputBox.ForEach(t => t.UpdateRead());
                EventBus.Default.PopUpSuccess("读取成功");
                EventBus.Default.Log(new LogInfo($"读取配方"));
            });
        }

        [RelayCommand]
        private void SlnWrite()
        {
            Task.Run(() =>
            {
                ListCheckBox.ForEach(t => t.UpdateWrite());
                ListSwitch.ForEach(t => t.UpdateWrite());
                ListInputBox.ForEach(t => t.UpdateWrite());
                EventBus.Default.PopUpSuccess("写入成功");
                EventBus.Default.Log(new LogInfo($"配方 [{SelectedSlnName}] 写入"));
            });
        }

        #endregion Command

        #region Init Event

        private void InitUI()
        { //上次Currid,
            CurrSlnId = int.Parse(RepositoryService<Config>.Instance.Query(t => t.Key.Equals("LastSlnId") && !t.IsDelete).FirstOrDefault().Value);
            SelectedSlnName = RepositoryService<SlnConfig>.Instance.Query(t => t.Id.Equals(CurrSlnId) && !t.IsDelete).FirstOrDefault()?.Name;
            ListSlnResource = RepositoryService<SlnConfig>.Instance.Query(t => !t.IsDelete).Select(t => t.Name).ToList();
        }

        private void Update2UI()
        {
            List<ButtonViewModel> primbuttons = new();
            List<ButtonViewModel> normbuttons = new();
            List<CheckBoxViewModel> checks = new();
            List<SwitchViewModel> switchs = new();
            List<InputSignalViewModel> inputsignales = new();
            List<DispBoxViewModel> dispboxes = new();
            List<InputBoxViewModel> inputboxes = new();
            List<AxisBoxViewModel> axis = new();

            //查出SlnParm的值
            var listSlnParm = RepositoryService<SlnParmConfig>.Instance.Query(t => t.SlnId.Equals(CurrSlnId) && !t.IsDelete);

            //查出Sln界面的寄存器
            var listregister = RepositoryService<RegisterConfig>.Instance.Query(t => t.Disp_SlnView && !t.IsDelete).OrderBy(t2 => t2.SortLevel).ToList();
            foreach (var item in listregister)
            {
                string slndata = string.Empty;
                int parmid = 0;
                foreach (var itemparm in listSlnParm)
                {
                    if (item.Id.Equals(itemparm.RegisterId))
                    {
                        parmid = itemparm.Id;
                        slndata = itemparm.Value;
                        break;
                    }
                }

                switch (item.ControlType)
                {
                    case EnumControlType.Switch:
                        switchs.Add(new SwitchViewModel(item) { SlnParmId = parmid, IsSwitchOn = string.IsNullOrEmpty(slndata) ? false : bool.Parse(slndata) });
                        break;

                    case EnumControlType.InputBox:
                        inputboxes.Add(new InputBoxViewModel(item) { SlnParmId = parmid, InputValue = string.IsNullOrEmpty(slndata) ? "0" : slndata });
                        break;

                    case EnumControlType.CheckBox:
                        checks.Add(new CheckBoxViewModel(item) { SlnParmId = parmid, IsChecked = string.IsNullOrEmpty(slndata) ? false : bool.Parse(slndata) });
                        break;

                    case EnumControlType.InputSignal:
                        inputsignales.Add(new InputSignalViewModel(item));
                        break;

                    case EnumControlType.DispDataBox:
                        dispboxes.Add(new DispBoxViewModel(item));
                        break;

                    case EnumControlType.NormButton:
                        normbuttons.Add(new ButtonNormViewModel(item));
                        break;

                    case EnumControlType.StartButton:
                        primbuttons.Add(new ButtonStartViewModel(item));
                        break;

                    case EnumControlType.EmgButton:
                        primbuttons.Add(new ButtonEmgViewModel(item));
                        break;

                    case EnumControlType.StopButton:
                        primbuttons.Add(new ButtonStopViewModel(item));
                        break;

                    case EnumControlType.PauseButton:
                        primbuttons.Add(new ButtonPauseViewModel(item));
                        break;

                    case EnumControlType.ResetButton:
                        primbuttons.Add(new ButtonResetViewModel(item));
                        break;

                    default:
                        break;
                }
            }
            primbuttons.AddRange(normbuttons);
            ListButton = primbuttons;

            ListCheckBox = checks;
            ListSwitch = switchs;
            ListInputSignal = inputsignales;

            ListInputBox = inputboxes;
            ListDispBox = dispboxes;

            RepositoryService<AxisConfig>.Instance.Query(t => !t.IsDelete).OrderBy(t2 => t2.SortLevel).ToList()
                .ForEach(x => axis.Add(new AxisBoxViewModel(x)));

            ListAxis = axis;

            VisiblityButton = ListButton.Count() > 0;
            VisiblityCheckBox = ListCheckBox.Count() > 0;
            VisiblitySwitch = ListSwitch.Count() > 0;
            VisiblityInputSignal = ListInputSignal.Count() > 0;
            VisiblityDispBox = ListDispBox.Count() > 0;
            VisiblityAxis = ListAxis.Count() > 0;
            VisiblityinputBox = ListInputBox.Count() > 0;
        }

        #endregion Init Event

        #region SLOT

        private void Register()
        {
            WeakReferenceMessenger.Default.Register<string, string>(this, "SlnViewLoadSignal", SlnViewLoadSlot);
            WeakReferenceMessenger.Default.Register<string, string>(this, "SlnViewUnLoadSignal", SlnViewUnLoadSlot);
        }

        private void SlnViewLoadSlot(object recipient, string message)
        {
            Task.Run(() =>
            {
                Update2UI();
                EventBus.Default.BindCircleTimeAction(CircleTimeActionSlot);
            });
        }

        private void CircleTimeActionSlot()
        {
            Task.Run(() =>
            {
                ListInputSignal.ForEach(T => T.UpdateRead());
                ListDispBox.ForEach(T => T.UpdateRead());

                var batchres = ModbusCtrl.Instance.BatchRead();
                var boolres = ModbusCtrl.Instance.BatchReadBool();
                if (batchres.IsSuccess && boolres.IsSuccess)
                {
                    var datares = batchres.Content;
                    var databoolres = boolres.Content;
                    ListDispBox.ForEach(t => t.ParsebyBatchData(ref datares, ref databoolres));
                    ListInputSignal.ForEach(t => t.ParsebyBatchData(ref datares, ref databoolres));
                }
                ListAxis.ForEach(t => t.UpdateRead());
            });




        }

        private void SlnViewUnLoadSlot(object recipient, string message)
        {
            EventBus.Default.UnBindCircleTimeAction(CircleTimeActionSlot);
        }

        #endregion SLOT

    }
}